package myJs.analysis

import myJs.Implicits._
import myJs.api.Api
import myJs.cps._
import myJs.myPkg.{LayerOptions, MyFetch, SwalOptions, layer, swal}
import myJs.tool.Tool
import slinky.core.FunctionalComponent
import slinky.core.annotations.react
import slinky.core.facade.Hooks._
import slinky.web.html._

import scala.scalajs.js.Dynamic.{global => g}
import myJs.myPkg.jquery.$
import shared.Pojo._
import org.scalajs.dom.html
import slinky.core.facade.React

import scala.collection.immutable.SeqMap
import scala.scalajs.js
import org.scalajs.macrotaskexecutor.MacrotaskExecutor.Implicits._
import shared.tsPojo.TsPojo
import upickle.default._
import typings.csstype.csstypeStrings

/**
 * Created by yz on 21/1/2022
 */
@react object SurvivalCp {

  type Props = Unit

  val component = FunctionalComponent[Props] { props =>

    val (geneName, setGeneName) = useState("")
    val (imgSrc, setImgSrc) = useState("")
    val (tumorType, setTumorType) = useState("HCC")
    val (survivalData, setSurvivalData) = useState("OS")
    val (upperCutoff, setUpperCutoff) = useState("Median")
    val (lowerCutoff, setLowerCutoff) = useState("Median")
    val (customUpperCutoff, setCustomUpperCutoff) = useState("")
    val (customLowerCutoff, setCustomLowerCutoff) = useState("")
    val (dataset, setDataset) = useState("")
    val (datasetMap, setDatasetMap) = useState(SeqMap[String, String]())
    val (geneData, setGeneData) = useState("")

    val tumorTypeMap = List("HCC", "ICC").optionMap
    val survivalDataMap = List("OS", "DSS", "DFS", "PFS").optionMap
    val upperCutoffMap = List("Median", "Quantile (75%)", "Custom (%)").optionMap
    val lowerCutoffMap = List("Median", "Quantile (25%)", "Custom (%)").optionMap

    val formRef = React.createRef[html.Form]

    object FTool {

      def refreshImg = () => {
        import TsPojo.analysis._
        if (geneName.nonBlank) {
          val bv = $(formRef.current).bv
          val invalidFields = bv.getInvalidFields()
          if (invalidFields.isEmpty) {
            Tool.useLoadingF() { () =>
              val curUpperCutoff = if (upperCutoff == "Custom (%)") customUpperCutoff else upperCutoff
              val curLowerCutoff = if (lowerCutoff == "Custom (%)") customLowerCutoff else lowerCutoff
              val reqeust = SurvivalImage.Request(geneName = geneName, tumorType = tumorType, dataset = dataset,
                survivalData = survivalData, upperCutoff = curUpperCutoff, lowerCutoff = curLowerCutoff)
              Api.analysis.survivalImage(reqeust).map { response =>
                if (response.valid) {
                  val src = s"data:image/png;base64,${response.base64}"
                  setImgSrc(src)
                  setGeneData(response.geneData)
                } else {
                  val options = SwalOptions(title = "Error", text = response.message, `type` = "error")
                  swal(options)
                }
              }
            }
          }
        } else {
          layer.msg("Please select Gene Symbol first!", LayerOptions(icon = 5, time = 3000))
        }
        ()
      }

      def geneNameChange = (v: String) => {
        setGeneName(v)
      }

      def tumorTypeChange = (v: String) => {
        setTumorType(v)
      }

      def refreshDatasetMap = {
        Api.getFileColumn("Gepliver_surv_all.txt", "Dataset_size").map { rs =>
          val curDatasetMap = rs.map { x =>
            (x, x)
          }.toSeqMap
          setDatasetMap(curDatasetMap)
          setDataset("Bulk-19(TCGA, HCC=361)")
        }
      }

      def datasetChange = (v: String) => {
        setDataset(v)
      }

      def survivalDataChange = (v: String) => {
        setSurvivalData(v)
      }

      def upperCutoffChange = (v: String) => {
        setUpperCutoff(v)
      }

      def lowerCutoffChange = (v: String) => {
        setLowerCutoff(v)
      }

      def customUpperCutoffChange = (v: String) => {
        setCustomUpperCutoff(v)
      }

      def customLowerCutoffChange = (v: String) => {
        setCustomLowerCutoff(v)
      }

      def bootstrapValidator = {
        val formJq = $(formRef.current)
        val dict: js.Dictionary[js.Any] = js.Dictionary(
          "feedbackIcons" -> js.Dictionary(
            "valid" -> "glyphicon glyphicon-ok",
            "invalid" -> "glyphicon glyphicon-remove",
            "validating" -> "glyphicon glyphicon-refresh",
          ),
          "excluded" -> js.Array(":disabled"),
          "fields" -> {
            js.Dictionary(
              "customUpperCutoff" -> {
                val info = "Upper Cutoff"
                js.Dictionary(
                  "validators" -> js.Dictionary(
                    "notEmpty" -> js.Dictionary(
                      "message" -> s"${info} is required！"
                    ),
                    "between" -> js.Dictionary(
                      "min" -> 0,
                      "max" -> 100,
                      "inclusive" -> false,
                      "message" -> s"${info} must be value k, which 0 <= k <= 100!",
                    ),
                  )
                )
              },
              "customLowerCutoff" -> {
                val info = "Lower Cutoff"
                js.Dictionary(
                  "validators" -> js.Dictionary(
                    "notEmpty" -> js.Dictionary(
                      "message" -> s"${info} is required！"
                    ),
                    "between" -> js.Dictionary(
                      "min" -> 0,
                      "max" -> 100,
                      "inclusive" -> false,
                      "message" -> s"${info} must be value k, which 0 <= k <= 100!",
                    ),
                  )
                )
              },
            )
          }
        )
        formJq.bootstrapValidator(dict)
      }

      def downloadCsv = () => {
        Tool.downloadCsv(s"${geneName}_surv.csv", geneData)
      }

      def imageName = s"${geneName}_survival"

      def downloadPng = () => {
        Tool.downloadPng(imgSrc = imgSrc, fileName = s"${imageName}.png")
      }

      def downloadJpeg = () => {
        Tool.downloadJpeg(imgSrc = imgSrc, fileName = s"${imageName}.jpeg")
      }

      def downloadPdf = () => {
        Tool.downloadPdf(imgSrc = imgSrc, fileName = s"${imageName}.pdf")
      }

      def downloadSvg = () => {
        Tool.downloadSvg(imgSrc = imgSrc, fileName = s"${imageName}.svg")
      }

    }

    useEffect(() => {
      FTool.refreshDatasetMap
      FTool.bootstrapValidator
    }, List()
    )

    val customUpperCutoffShow = (upperCutoff == "Custom (%)")
    val customLowerCutoffShow = (lowerCutoff == "Custom (%)")

    div(

      div(
        div(style := Style(display = csstypeStrings.flex, width = "100%"),
          div(style := Style(flex = 4.5),

            form(className := "form-horizontal", ref := formRef,

              div(style := Style(display = csstypeStrings.flex, marginRight = 15), className := "form-group",
                div(style := Style(flex = 3, display = csstypeStrings.flex, justifyContent = csstypeStrings.`flex-end`),
                  label(style := Style(paddingTop = 15), className := "control-label",
                    "Gene Symbol:"),
                ),
                div(style := Style(flex = 5, height = 34, display = csstypeStrings.flex, alignItems = csstypeStrings.center,
                  paddingTop = 15, paddingLeft = 15, paddingRight = 15),
                  {
                    val url = s"${Api.apiUrl}/gepLiver/analysis/getAllGene"
                    PureAsyncSelect2Cp(width = "100%", onChange = FTool.geneNameChange, name = "geneName", url = url)
                  }

                ),
                div(style := Style(flex = 2, display = csstypeStrings.flex))
              ),

              div(style := Style(display = csstypeStrings.flex, marginRight = 15), className := "form-group",
                div(style := Style(flex = 3, display = csstypeStrings.flex, justifyContent = csstypeStrings.`flex-end`),
                  label(style := Style(paddingTop = 15), className := "control-label",
                    "Tumor Type:"),
                ),
                div(style := Style(flex = 5, height = 34, display = csstypeStrings.flex, alignItems = csstypeStrings.center,
                  paddingTop = 15, paddingLeft = 15, paddingRight = 15),
                  PureSelectCp(onChange = FTool.tumorTypeChange, value = tumorType, optionMap = tumorTypeMap)
                ),
                div(style := Style(flex = 2, display = csstypeStrings.flex))
              ),

              div(style := Style(display = csstypeStrings.flex, marginRight = 15, marginBottom = 5), className := "form-group",
                div(style := Style(flex = 3, display = csstypeStrings.flex, justifyContent = csstypeStrings.`flex-end`),
                  label(style := Style(paddingTop = 15), className := "control-label",
                    "Dataset:",
                  ),
                ),
                div(style := Style(flex = 5, paddingTop = 11, paddingLeft = 15, paddingRight = 15),
                  PureSelect2Cp(optionMap = datasetMap, onChange = FTool.datasetChange, value = dataset,
                    width = "100%", name = "datasets")
                ),
                div(style := Style(flex = 2, display = csstypeStrings.flex))
              ),

              div(style := Style(display = csstypeStrings.flex, marginRight = 15), className := "form-group",
                div(style := Style(flex = 3, display = csstypeStrings.flex, justifyContent = csstypeStrings.`flex-end`),
                  label(style := Style(paddingTop = 15), className := "control-label",
                    "Survival Data:"),
                ),
                div(style := Style(flex = 5, height = 34, display = csstypeStrings.flex, alignItems = csstypeStrings.center,
                  paddingTop = 15, paddingLeft = 15, paddingRight = 15),
                  PureSelectCp(onChange = FTool.survivalDataChange, value = survivalData, optionMap = survivalDataMap)
                ),
                div(style := Style(flex = 2, display = csstypeStrings.flex))
              ),

              div(style := Style(display = csstypeStrings.flex, marginRight = 15), className := "form-group",
                div(style := Style(flex = 3, display = csstypeStrings.flex, justifyContent = csstypeStrings.`flex-end`),
                  label(style := Style(paddingTop = 15), className := "control-label",
                    "Upper Cutoff:"),
                ),
                div(style := Style(flex = 4, height = 34, display = csstypeStrings.flex, alignItems = csstypeStrings.center,
                  paddingTop = 15, paddingLeft = 15, paddingRight = 15),
                  PureSelectCp(onChange = FTool.upperCutoffChange, value = upperCutoff, optionMap = upperCutoffMap)
                ),
                div(style := Style(flex = 3, paddingTop = 7),
                  div(style := Style(display = Tool.b2Display(customUpperCutoffShow), width = "100%",
                    paddingRight = 0, paddingLeft = 0),
                    className := "col-sm-3",
                    PureInputCp(value = customUpperCutoff, onChange = FTool.customUpperCutoffChange,
                      name = "customUpperCutoff", hasBv = true, formRef = formRef, show = customUpperCutoffShow)
                  )

                )
              ),

              div(style := Style(display = csstypeStrings.flex, marginRight = 15), className := "form-group",
                div(style := Style(flex = 3, display = csstypeStrings.flex, justifyContent = csstypeStrings.`flex-end`),
                  label(style := Style(paddingTop = 15), className := "control-label",
                    "Lower Cutoff:"),
                ),
                div(style := Style(flex = 4, height = 34, display = csstypeStrings.flex, alignItems = csstypeStrings.center,
                  paddingTop = 15, paddingLeft = 15, paddingRight = 15),
                  PureSelectCp(onChange = FTool.lowerCutoffChange, value = lowerCutoff, optionMap = lowerCutoffMap)
                ),
                div(style := Style(flex = 3, paddingTop = 7),
                  div(style := Style(display = Tool.b2Display(customLowerCutoffShow), width = "100%",
                    paddingRight = 0, paddingLeft = 0),
                    className := "col-sm-3",
                    PureInputCp(value = customLowerCutoff, onChange = FTool.customLowerCutoffChange,
                      name = "customLowerCutoff", hasBv = true, formRef = formRef, show = customLowerCutoffShow)
                  )

                )
              ),

              div(className := "form-group",
                div(className := "actions col-sm-offset-2 col-sm-3",
                  button(style := Style(width = "95%"), `type` := "button", className := "btn btn-primary myAddShow",
                    onClick := FTool.refreshImg,
                    s" Plot"
                    ,
                  ),
                ),
              ),
            ),

          ),
          div(style := Style(flex = 4.5),
            div(style := Style(display = Tool.b2Display(imgSrc.nonBlank)),
              div(style := Style(display = csstypeStrings.flex, justifyContent = csstypeStrings.`flex-end`),
                a(onClick := FTool.downloadCsv, className := "btn  btn-default", title := "Export data",
                  i(className := "glyphicon glyphicon-export")
                ),
                div(style := Style(marginLeft = 5), className := "btn-group",
                  a(title := "Export image", className := "btn  btn-default idsButton", data - "toggle" := "dropdown",
                    data - "hover" := "dropdown", data - "close-others" := "true", aria - "expanded" := "false",
                    i(className := "fa fa-bars")
                  ),
                  ul(className := "dropdown-menu pull-right",
                    li(
                      a(onClick := FTool.downloadPng, "Download PNG image")
                    ),
                    li(
                      a(onClick := FTool.downloadJpeg, "Download JPEG image")
                    ),
                    li(
                      a(onClick := FTool.downloadPdf, "Download PDF image")
                    ),
                    li(
                      a(onClick := FTool.downloadSvg, "Download SVG image")
                    ),
                  )
                )

              ),
              img(className := "mySvg", id := "boxplotImg", src := imgSrc)
            ),

          ),
          div(style := Style(flex = 1))
        )
      )


    )

  }

  object STool {


  }

}
